package code.example.base.gc.gc4;

import code.example.base.gc.Person;

import java.util.LinkedList;
import java.util.Queue;
import java.util.concurrent.TimeUnit;

/**
 *   java -Xms512m -Xmx512m -Xmn100m -XX:SurvivorRatio=5  -XX:+PrintTenuringDistribution -XX:-UseAdaptiveSizePolicy -XX:+PrintGCDetails -XX:+PrintHeapAtGC -cp ./lib/*:*.jar  code.example.base.gc.gc4.TriggerGC4
 *
 *     -Xmn100m   :年轻代大小设为100M
 *     -XX:SurvivorRatio=5 :survivor 大小约 100/7 = 14m.
 *
 *   目的： 一直存活的对象大于survivor大小，总量200000个元素，存活对象一直在变，观察看GC情况
 *   场景：LinkedList 中存200000个元素，然后进入循环（尾部添加500个，头部移除500个），即LinkedList不断的进入新元素移除旧元素，但总量一直保存 200000个元素，
 *   GC情况（见 gc1.context）:
        每次minor GC时，survivor空间存不下当前存活的对象，就不断的向old的添加新数据，导到old不断的增长，
        每次minor GC之后，survivor空间99%-100%，old 每次都增长。最终导至FULL  LKD
        minor gc 时间约130ms左右。 gc 时间相对过长。
 [GC (Allocation Failure) [PSYoungGen: 88048K->14336K(88064K)] 131440K->62528K(509952K), 0.1297659 secs] [Times: user=1.01 sys=0.00, real=0.13 secs]
 Heap after GC invocations=10 (full 0):
 PSYoungGen      total 88064K, used 14336K [0x00000000f9c00000, 0x0000000100000000, 0x0000000100000000)
 eden space 73728K, 0% used [0x00000000f9c00000,0x00000000f9c00000,0x00000000fe400000)
 from space 14336K, 100% used [0x00000000ff200000,0x0000000100000000,0x0000000100000000)
 to   space 14336K, 0% used [0x00000000fe400000,0x00000000fe400000,0x00000000ff200000)

    原因分析：
       GC 触发时，LinkedList 保存着200000至200500个元素（看gc 触发的时间点）
                 而这200000个元素，是放不进survivor中的，所以不断的存入old. gc时间过长。
    优化方式:增加survivor 空间，能够存下200000个元素
            java -Xms512m -Xmx512m -Xmn100m -XX:SurvivorRatio=3  -XX:+PrintTenuringDistribution -XX:-UseAdaptiveSizePolicy -XX:+PrintGCDetails -XX:+PrintHeapAtGC -cp ./lib/*:*.jar  code.example.base.gc.gc4.TriggerGC4
              -XX:SurvivorRatio=3 :survivor 大小约 100/5 = 20m.
    观察GC情况：
         每次minor GC时,survivor 都能存放下对象，old 始终是0%。survivor 占用空间保持在90%以上。
         minor GC 回收时间 130ms ,左右，与上面相同，只是少了full gc的回收时间。
         eden
 [GC (Allocation Failure) [PSYoungGen: 80352K->18944K(81920K)] 80672K->19264K(503808K), 0.1246097 secs] [Times: user=0.98 sys=0.00, real=0.12 secs]
 Heap after GC invocations=17 (full 0):
 PSYoungGen      total 81920K, used 18944K [0x00000000f9c00000, 0x0000000100000000, 0x0000000100000000)
 eden space 61440K, 0% used [0x00000000f9c00000,0x00000000f9c00000,0x00000000fd800000)
 from space 20480K, 92% used [0x00000000fd800000,0x00000000fea80000,0x00000000fec00000)
 to   space 20480K, 0% used [0x00000000fec00000,0x00000000fec00000,0x0000000100000000)
 ParOldGen       total 421888K, used 320K [0x00000000e0000000, 0x00000000f9c00000, 0x00000000f9c00000)
 object space 421888K, 0% used [0x00000000e0000000,0x00000000e0050050,0x00000000f9c00000)

    问题：能否减少 minor gc 执行时间？？
    尝试:增加survivor 空间，再试一下
        java -Xms512m -Xmx512m -Xmn130m -XX:SurvivorRatio=3  -XX:+PrintTenuringDistribution -XX:-UseAdaptiveSizePolicy -XX:+PrintGCTaskTimeStamps -XX:+PrintGCDetails -XX:+PrintHeapAtGC -cp ./lib/*:*.jar  code.example.base.gc.gc4.TriggerGC4
        survivor 空间增加了 6M， 加收之后对比：占用空间由 90% 下降到 72%，minor gc时间未减少。

 [GC (Allocation Failure) [PSYoungGen: 99056K->19216K(106496K)] 99064K->19232K(497664K), 0.1255515 secs] [Times: user=0.96 sys=0.00, real=0.12 secs]
 Heap after GC invocations=4 (full 0):
 PSYoungGen      total 106496K, used 19216K [0x00000000f7e00000, 0x0000000100000000, 0x0000000100000000)
 eden space 79872K, 0% used [0x00000000f7e00000,0x00000000f7e00000,0x00000000fcc00000)
 from space 26624K, 72% used [0x00000000fe600000,0x00000000ff8c4010,0x0000000100000000)
 to   space 26624K, 0% used [0x00000000fcc00000,0x00000000fcc00000,0x00000000fe600000)
 ParOldGen       total 391168K, used 16K [0x00000000e0000000, 0x00000000f7e00000, 0x00000000f7e00000)
 object space 391168K, 0% used [0x00000000e0000000,0x00000000e0004000,0x00000000f7e00000)
 Metaspace       used 2975K, capacity 4490K, committed 4864K, reserved 1056768K
 class space    used 328K, capacity 386K, committed 512K, reserved 1048576K
 }

  那么如何减少minor gc 执行时间？？
   见TriggerGC5





 */
public class TriggerGC4 {

    public void test(){
        Queue data = new LinkedList();
        for(int i=0;i<200000;i++){//  增大10000
            Person person = new Person();
            person.setName("TestK"+i);
            data.offer(person);
        }
        for(;;){

            for(int i=0;i<500;i++){
                Person person = new Person();
                person.setName("TestK"+i);
                data.offer(person);
            }
            for(int i=0;i<500;i++){
                data.poll();
            }
            //LogFactory.getLog().info("queue.size="+data.size());
            try {
                TimeUnit.MILLISECONDS.sleep(3);
            }catch (Exception e){}
        }
    }
    public static void main(String [] args){
        new TriggerGC4().test();
    }
}
